home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / Image / IPTC.php < prev   
PHP Script  |  2004-03-24  |  11KB  |  434 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 2003-2004 TownNews.com                                 |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Patrick O'Lone <polone@townnews.com>                        |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // IPTC.php,v 1.5 2003/08/12 14:15:55 polone Exp
  20.  
  21. /**
  22. * An abstraction layer for working with IPTC fields
  23. *
  24. * This class encapsulates the functions iptcparse() and iptcembed(). It provides
  25. * the necessary methods for extracting, modifying, and saving IPTC data with
  26. * image files (JPEG and TIFF files only).
  27. *
  28. * @author Patrick O'Lone <polone@townnews.com>
  29. * @copyright 2003-2004 TownNews.com
  30. * @version 1.5
  31. */
  32. class Image_IPTC
  33. {
  34.     /**
  35.     * @var string
  36.     * The name of the image file that contains the IPTC fields to extract and
  37.     * modify.
  38.     * @see Image_IPTC()
  39.     * @access private
  40.     */
  41.     var $_sFilename = null;
  42.  
  43.     /**
  44.     * @var array
  45.     * The IPTC fields that were extracted from the image or updated by this
  46.     * class.
  47.     * @see getAllTags(), getTag(), setTag()
  48.     * @access private
  49.     */
  50.     var $_aIPTC = array();
  51.  
  52.     /**
  53.     * @var boolean
  54.     * The state of the getimagesize() function. If the parsing was successful,
  55.     * this value will be set to true if the APP header data could be obtained.
  56.     * @see isValid()
  57.     * @access private
  58.     */
  59.     var $_bIPTCParse = false;
  60.  
  61.     /**
  62.     * Constructor
  63.     *
  64.     * @param string
  65.     * The name of the image file to access and extract IPTC information from.
  66.     *
  67.     * @access public
  68.     */
  69.     function Image_IPTC( $sFilename )
  70.     {
  71.         $this->_sFilename = $sFilename;
  72.  
  73.         if (is_file($this->_sFilename)) {
  74.  
  75.            if (@getimagesize($this->_sFilename, $aAPP) && !empty($aAPP)) {
  76.  
  77.                $this->_aIPTC = @iptcparse($aAPP['APP13']);
  78.                $this->_bIPTCParse = true;
  79.  
  80.            }
  81.  
  82.         }
  83.  
  84.     }
  85.  
  86.     /**
  87.     * Returns the status of IPTC parsing during instantiation
  88.     *
  89.     * You'll normally want to call this method before trying to change or
  90.     * get IPTC fields.
  91.     *
  92.     * @return boolean
  93.     * Returns true if the getimagesize() function successfully extracted APP
  94.     * information from the supplied file
  95.     *
  96.     * @access public
  97.     */
  98.     function isValid()
  99.     {
  100.         return $this->_bIPTCParse;
  101.     }
  102.  
  103.     /**
  104.     * Set IPTC fields to a specific value or values
  105.     *
  106.     * @param mixed
  107.     * The field (by number or string) of the IPTC data you wish to update
  108.     *
  109.     * @param mixed
  110.     * If the value supplied is scalar, then the block assigned will be set to
  111.     * the given value. If the value supplied is an array, then the entire tag
  112.     * will be given the value of the array.
  113.     *
  114.     * @param integer
  115.     * The block to update. Most tags only use the 0th block, but certain tags,
  116.     * like the "keywords" tag, use a list of values. If set to a negative
  117.     * value, the entire tag block will be replaced by the value of the second
  118.     * parameter.
  119.     *
  120.     * @access public
  121.     */
  122.     function setTag( $xTag, $xValue, $nBlock = 0 )
  123.     {
  124.         $sTagName = $this->_lookupTag($xTag);
  125.  
  126.         if (($nBlock < 0) || is_array($xValue)) {
  127.  
  128.             $this->_aIPTC[$sTagName] = $xValue;
  129.  
  130.         } else {
  131.  
  132.             $this->_aIPTC[$sTagName][$nBlock] = $xValue;
  133.  
  134.         }
  135.     }
  136.  
  137.     /**
  138.     * Get a specific tag/block from the IPTC fields
  139.     *
  140.     * @return mixed
  141.     * If the requested tag exists, a scalar value will be returned. If the block
  142.     * is negative, the entire
  143.     *
  144.     * @param mixed
  145.     * The tag name (by number or string) to access. For a list of possible string
  146.     * values look at the _lookupTag() method.
  147.     *
  148.     * @param integer
  149.     * The block to reference. Most fields only have one block (the 0th block),
  150.     * but others, like the "keywords" block, are an array. If you want
  151.     * to get the whole array, set this to a negative number like -1.
  152.     *
  153.     * @see _lookupTag()
  154.     * @access public
  155.     */
  156.     function getTag( $xTag, $nBlock = 0 )
  157.     {
  158.         $sTagName = $this->_lookupTag($xTag);
  159.  
  160.         if (isset($this->_aIPTC[$sTagName]) && is_array($this->_aIPTC[$sTagName])) {
  161.  
  162.             if ($nBlock < 0) {
  163.  
  164.                 return $this->_aIPTC[$sTagName];
  165.  
  166.             } else if (isset($this->_aIPTC[$sTagName][$nBlock])) {
  167.  
  168.                 return $this->_aIPTC[$sTagName][$nBlock];
  169.  
  170.             }
  171.  
  172.         }
  173.  
  174.         return null;
  175.     }
  176.  
  177.     /**
  178.     * Get a copy of all IPTC tags extracted from the image
  179.     *
  180.     * @return array
  181.     * An array of IPTC fields as it extracted by the iptcparse() function
  182.     *
  183.     * @access public
  184.     */
  185.     function getAllTags()
  186.     {
  187.         return $this->_aIPTC;
  188.     }
  189.  
  190.     /**
  191.     * Save the IPTC block to an image file
  192.     *
  193.     * @return boolean
  194.     *
  195.     * @param string
  196.     * If supplied, the altered IPTC block and image data will be saved to another
  197.     * file instead of the same file.
  198.     *
  199.     * @access public
  200.     */
  201.     function save( $sOutputFile = null )
  202.     {
  203.         if (empty($sOutputFile)) {
  204.  
  205.            $sOutputFile = $this->_sFilename;
  206.  
  207.         }
  208.  
  209.         $sIPTCBlock = $this->_getIPTCBlock();
  210.         $sImageData = @iptcembed($sIPTCBlock, $this->_sFilename, 0);
  211.  
  212.         $hImageFile = @fopen($sOutputFile, 'wb');
  213.         if (is_resource($hImageFile)) {
  214.  
  215.            flock($hImageFile, LOCK_EX);
  216.            fwrite($hImageFile, $sImageData);
  217.            flock($hImageFile, LOCK_UN);
  218.            return fclose($hImageFile);
  219.  
  220.         }
  221.  
  222.         return false;
  223.     }
  224.  
  225.     /**
  226.     * Embed IPTC data block and output to standard output
  227.     *
  228.     * @access public
  229.     */
  230.     function output()
  231.     {
  232.         $sIPTCBlock = $this->_getIPTCBlock();
  233.         @iptcembed($sIPTCBlock, $this->_sFilename, 2);
  234.     }
  235.  
  236.     /**
  237.     * Return the numeric code of an IPTC field name
  238.     *
  239.     * @return integer
  240.     * Returns a numeric code corresponding to the name of the IPTC field that
  241.     * was supplied.
  242.     *
  243.     * @param string
  244.     * A field name representing the type of tag to return
  245.     *
  246.     * @access private
  247.     */
  248.     function _lookupTag( $sTag )
  249.     {
  250.         $nTag = -1;
  251.         $sTag = strtolower(str_replace(' ','_',$sTag));
  252.  
  253.         switch($sTag) {
  254.  
  255.           case 'object_name':
  256.              $nTag = 5;
  257.              break;
  258.  
  259.           case 'edit_status':
  260.              $nTag = 7;
  261.              break;
  262.  
  263.           case 'priority':
  264.              $nTag = 10;
  265.              break;
  266.  
  267.           case 'category':
  268.              $nTag = 15;
  269.              break;
  270.  
  271.           case 'supplementary_category':
  272.              $nTag = 20;
  273.              break;
  274.  
  275.           case 'fixture_identifier':
  276.              $nTag = 22;
  277.              break;
  278.  
  279.           case 'keywords':
  280.              $nTag = 25;
  281.              break;
  282.  
  283.           case 'release_date':
  284.              $nTag = 30;
  285.              break;
  286.  
  287.           case 'release_time':
  288.              $nTag = 35;
  289.              break;
  290.  
  291.           case 'special_instructions':
  292.              $nTag = 40;
  293.              break;
  294.  
  295.           case 'reference_service':
  296.              $nTag = 45;
  297.              break;
  298.  
  299.           case 'reference_date':
  300.              $nTag = 47;
  301.              break;
  302.  
  303.           case 'reference_number':
  304.              $nTag = 50;
  305.              break;
  306.  
  307.           case 'created_date':
  308.              $nTag = 55;
  309.              break;
  310.  
  311.           case 'originating_program':
  312.              $nTag = 64;
  313.              break;
  314.  
  315.           case 'program_version':
  316.              $nTag = 70;
  317.              break;
  318.  
  319.           case 'object_cycle':
  320.              $nTag = 75;
  321.              break;
  322.  
  323.           case 'byline':
  324.              $nTag = 80;
  325.              break;
  326.  
  327.           case 'byline_title':
  328.              $nTag = 85;
  329.              break;
  330.  
  331.           case 'city':
  332.              $nTag = 90;
  333.              break;
  334.  
  335.           case 'province_state':
  336.              $nTag = 95;
  337.              break;
  338.  
  339.           case 'country_code':
  340.              $nTag = 100;
  341.              break;
  342.  
  343.           case 'country':
  344.              $nTag = 101;
  345.              break;
  346.  
  347.           case 'original_transmission_reference':
  348.              $nTag = 103;
  349.              break;
  350.  
  351.           case 'headline':
  352.              $nTag = 105;
  353.              break;
  354.  
  355.           case 'credit':
  356.              $nTag = 110;
  357.              break;
  358.  
  359.           case 'source':
  360.              $nTag = 115;
  361.              break;
  362.  
  363.           case 'copyright_string':
  364.              $nTag = 116;
  365.              break;
  366.  
  367.           case 'caption':
  368.              $nTag = 120;
  369.              break;
  370.  
  371.           case 'local_caption':
  372.              $nTag = 121;
  373.              break;
  374.  
  375.         }
  376.  
  377.         if ($nTag > 0) {
  378.  
  379.            return sprintf('2#%03d', $nTag);
  380.  
  381.         }
  382.  
  383.         return 0;
  384.     }
  385.  
  386.     /**
  387.     * Generate an IPTC block from the current tags
  388.     *
  389.     * @return string
  390.     * Returns a binary string that contains the new IPTC block that can be used
  391.     * in the iptcembed() function call
  392.     *
  393.     * @access private
  394.     */
  395.     function &_getIPTCBlock()
  396.     {
  397.         $sIPTCBlock = null;
  398.  
  399.         foreach($this->_aIPTC as $sTagID => $aTag) {
  400.  
  401.             $sTag = str_replace('2#', null, $sTagID);
  402.             for($ci = 0; $ci < sizeof($aTag); $ci++) {
  403.  
  404.                 $nLen = strlen($aTag[$ci]);
  405.  
  406.                 // The below code is based on code contributed by Thies C. Arntzen
  407.                 // on the PHP website at the URL: http://www.php.net/iptcembed
  408.  
  409.                 $sIPTCBlock .= pack('C*', 0x1C, 2, $sTag);
  410.  
  411.                 if ($nLen < 32768) {
  412.  
  413.                     $sIPTCBlock .= pack('C*', $nLen >> 8, $nLen & 0xFF);
  414.  
  415.                 } else {
  416.  
  417.                     $sIPTCBlock .= pack('C*', 0x80, 0x04);
  418.                     $sIPTCBlock .= pack('C', $nLen >> 24 & 0xFF);
  419.                     $sIPTCBlock .= pack('C', $nLen >> 16 & 0xFF);
  420.                     $sIPTCBlock .= pack('C', $nLen >> 8 & 0xFF);
  421.                     $sIPTCBlock .= pack('C', $nLen & 0xFF);
  422.  
  423.                 }
  424.  
  425.                 $sIPTCBlock .= $aTag[$ci];
  426.             }
  427.         }
  428.  
  429.         return $sIPTCBlock;
  430.     }
  431. }
  432.  
  433. ?>
  434.